#include<cmath>
#include<iostream>


using namespace std;


class Roots
{
	static const double tolerence=0.0001;
	
	double f(double x);
	double df(double x);
	
public:

	long eqnum,iterations;
	
	double bisection(double a,double b);
	double regulafalsi(double a,double b);
	double newtonraphson(double xi);
	
};


double Roots::f(double x)
{
	switch(eqnum)
	{
		case 2:
			return 2*x*x-1;
			break;
			
		case 3:
			return 4*pow(x,3) - 3*x;
			break;
			
		case 4:
			return 8*pow(x,4) - 8*pow(x,2) +1;
			break;
			
		case 5:
			return 16*pow(x,5)-20*pow(x,3)+5*x;
			break;
			
	}

}



double Roots::df(double x)
{
	switch(eqnum)
	{
		case 2:
			return 4*x;
			break;
			
		case 3:
			return 12*pow(x,2) - 3;
			break;
			
		case 4:
			return 32*pow(x,3) - 16*x ;
			break;
			
		case 5:
			return 80*pow(x,4)-60*pow(x,2)+5;
			break;
			
	}

}


double Roots::bisection(double a,double b)
{
	double troot=(a+b)/2;
	iterations++;
	
	if(abs(f(troot))<tolerence) return troot;
	else
	{
		if(f(a)*f(troot) <0)
		{
			return bisection(a,troot);
		}
		else
		{
			return bisection(troot,b);
		}
	
	}

}


double Roots::regulafalsi(double a,double b)
{
	double c= (a*f(b) - b*f(a))/(f(b)-f(a));
	iterations++;
	
	if(abs(f(c))<tolerence) return c;
	else
	{
		if(f(a)*f(c) <0)
		{
			return regulafalsi(a,c);
		}
		else
		{
			return regulafalsi(c,b);
		}
	
	}

}


double Roots::newtonraphson(double xi)
{
	double xii= xi-(f(xi)/df(xi));
	iterations++;
	
	if(abs(f(xii)<tolerence)) return xii;
	else return newtonraphson(xii);
	
}
	



//  #############        main  starts here       ###################


int main()
{

	cout <<"\n           CALCULATION OF ROOTS USING NUMERICAL METHODS\n\n";	
	cout.precision(10);
	
	Roots root; 
	
	double a=-1,b=1.00001;
	double x0=(a+b)/2;
	double ans;
	
	/*     //test code 
	double root.trapezoidal(10000);
	double kk=3.5555555555123;
	
	cout<<"\n\nANS : " <<4*t <<"  nothing : " <<kk <<"\n\n";
	*/
	
	int i;
	for(i=2;i<=5;i++)
	{
		root.eqnum=i;
		cout <<"\n\n                          EQUATION " <<i;
		
		root.iterations=0;
		ans=root.bisection(a,b);
		cout<<"\n\nBISECTION :   iterations : "  <<root.iterations  <<"   ANS : " <<ans;
		
		root.iterations=0;
		ans=root.regulafalsi(a,b);
		cout<<"\n\nREGULA FALSI :   iterations : "  <<root.iterations  <<"   ANS : " <<ans;
		
		root.iterations=0;
		ans=root.newtonraphson(x0);
		cout<<"\n\nNEWTON RAPHSON :   iterations : "  <<root.iterations  <<"   ANS : " <<ans;
	}
	
	cout <<"\n";
	
	return 0;
}


